package cn.piggy.gateway.core.socket.parser;


import cn.piggy.gateway.common.dto.FileDto;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;


public class RequestParser {

    private final FullHttpRequest request;

    public RequestParser(FullHttpRequest request) {
        this.request = request;
    }

    /**
     * 简单处理请求路径
     */
    public String getUri() {
        String uri = request.uri();
        int idx = uri.indexOf("?");
        uri = idx > 0 ? uri.substring(0, idx) : uri;
        if (uri.equals("/favicon.ico"))
            return null;
        return uri;
    }

    /**
     * 解析封装请求参数
     */
    public Map<String, Object> parse() {
        // 获取请求类型
        HttpMethod method = request.method();
        if (HttpMethod.GET == method || HttpMethod.DELETE == method) {
            Map<String, Object> parameterMap = new HashMap<>();
            QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
            decoder.parameters().forEach((key, value) -> {
                if(value.size()>1){
                    parameterMap.put(key, value);
                }else{
                    parameterMap.put(key, value.get(0));
                }
            });
            return parameterMap;
        } else if (HttpMethod.POST == method || HttpMethod.PUT == method) {
            String contentType = getContentType();
            switch (contentType) {
                case "multipart/form-data":
                case "application/x-www-form-urlencoded":
                    JSONObject jsonObject = new JSONObject();
                    HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(request);
                    List<InterfaceHttpData> bodyHttpData = decoder.getBodyHttpDatas();
                    for(InterfaceHttpData data : bodyHttpData){
                        try{
                            if(data.getHttpDataType() == InterfaceHttpData.HttpDataType.FileUpload) {
                                MixedFileUpload fileUpload = (MixedFileUpload) data;
                                String name = data.getName();
                                Object o = jsonObject.get(name);
                                byte[] bytes = fileUpload.get();
                                String filename = fileUpload.getFilename();
                                FileDto f = new FileDto();
                                f.setBytes(bytes);
                                f.setFilename(filename);
                                if(o==null){
                                    jsonObject.put(name,f);
                                }else{
                                    if(o instanceof ArrayList){
                                        ((ArrayList<FileDto>) o).add(f);
                                    }else{
                                        ArrayList<FileDto> files = new ArrayList<>();
                                        files.add((FileDto)o);
                                        files.add(f);
                                        jsonObject.put(name,files);
                                    }
                                }
                            }else if(data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
                                Attribute attr = (Attribute) data;
                                Object o = jsonObject.get(attr.getName());
                                if(o==null){
                                    jsonObject.put(attr.getName(), attr.getValue());
                                }else{
                                    if(o instanceof ArrayList){
                                        ((ArrayList<Object>) o).add(o);
                                    }else{
                                        ArrayList<Object> jsonObjects = new ArrayList<>();
                                        jsonObjects.add(o);
                                        jsonObjects.add(attr.getValue());
                                        jsonObject.put(attr.getName(),jsonObjects);
                                    }
                                }
                            }
                        }catch (IOException e){
                            e.printStackTrace();
                        }
                    }
                    return jsonObject;
                case "application/json":
                    ByteBuf byteBuf = request.content().copy();
                    String content = byteBuf.toString(StandardCharsets.UTF_8);
                    return JSON.parseObject(content);
                case "none":
                    return new HashMap<>();
                default:
                    throw new RuntimeException("未实现的协议类型 Content-Type：" + contentType);
            }
        }
        throw new RuntimeException("未实现的请求类型 HttpMethod：" + method);
    }

    /*
     * POST /wg/activity/insert HTTP/1.1
     * Content-Type: application/json
     * User-Agent: PostmanRuntime/7.29.2
     * Postman-Token: xxx
     * Host: localhost:7397
     * Accept-Encoding: gzip, deflate, br
     * Connection: keep-alive
     * Content-Length: 45
     */
    private String getContentType() {
//        System.out.println(request.headers());
        Optional<Map.Entry<String, String>> header = request.headers().entries().stream().filter(
                val -> val.getKey().equals("Content-Type")
        ).findAny();
        Map.Entry<String, String> entry = header.orElse(null);
        if (null == entry)
            return "none";
        // application/json
        // multipart/form-data
        String contentType = entry.getValue();
        int idx = contentType.indexOf(";");
        if (idx > 0) {
            return contentType.substring(0, idx);
        } else {
            return contentType;
        }
    }

}
